﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SingleInstanceHelper.cs" company="TechBits">
//   Copyright (c) TechBits. All rights reserved.
// </copyright>
// <author>
//   Leandro G. Vacirca
// </author>
// <summary>
//   Defines the SingleInstanceHelper type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace IntelliShortCut.Application.Helpers
{
    using System;
    using System.Reflection;
    using System.Threading;
    using System.Windows.Forms;
    using log4net;

    /// <summary>
    /// SingleInstanceHelper implements functionality to create single instance WinForms applications.
    /// </summary>
    public sealed class SingleInstanceHelper
    {
        #region "Private Members"

        /// <summary>
        /// Mutex Name Format.
        /// </summary>
        private const string FORMAT_MUTEX_NAME = "SingleInstanceMutex-{0}-{1}";

        /// <summary>
        /// Holds the mutex for this application.
        /// </summary>
        private static Mutex singleInstance;

        /// <summary>
        /// Gets a unique identifier for this application's mutex based on its assembly name and version.
        /// </summary>
        private static string UniqueIdentifier
        {
            get
            {
                var appName = string.Empty;
                var appVersion = "0.0.0.0";
                var entry = Assembly.GetEntryAssembly();

                if (entry != null)
                {
                    var assemblyName = entry.GetName();
                    appName = assemblyName.Name;
                    appVersion = assemblyName.Version.ToString();
                }

                return string.Format(FORMAT_MUTEX_NAME, appName, appVersion);
            }
        }

        #endregion

        #region "Public Methods"

        /// <summary>
        /// Proxy method used by WinForm apps that want single instance behavior.
        /// This method will check if this is the first instance and create a new form of the
        /// specified type.  Otherwise, it will find the currently running instance and bring it
        /// to the foreground.
        /// </summary>
        /// <param name="newFormType">Type of the form to create if this is the first instance.</param>
        /// <param name="windowName">The window Name.</param>
        public static void ProxyMain(Type newFormType, string windowName)
        {
            try
            {
                // First, we create an instance of the Mutex with the appropriate identifier for this app
                singleInstance = new Mutex(false, UniqueIdentifier);

                // Then, we attempt to lock the Mutex to see if its the first intance (A Mutex can only ever have one lock on it at a time)
                if (singleInstance.WaitOne(1, true))
                {
                    // If this is the first instance, then create an instance of the main Form
                    var constructor = newFormType.GetConstructor(Type.EmptyTypes);
                    var newForm = (Form) constructor.Invoke(null);
                    Application.Run(newForm);
                }
                else
                {
                    // If its not the first instance, then hides the form
                    WindowsHelper.HideWindow(windowName);
                }
            }
            catch (Exception ex)
            {                
                LogManager.GetLogger(typeof(SingleInstanceHelper)).Error(ex);
            }
        }

        #endregion
    }
}